#ifndef MD5_H
#define MD5_H

typedef struct
{
    unsigned int count[2];      /* 数据的bit数计数器(对2^64取余) */
    unsigned int state[4];      /* A,B,C,D四个常数 */
    unsigned char buffer[64];   /* 输入数据缓冲区 */
} MD5_CTX;

// F,G,H,I四个非线性变换函数
#define F(x, y, z) ((x & y) | (~x & z))
#define G(x, y, z) ((x & z) | (y & ~z))
#define H(x, y, z) (x ^ y ^ z)
#define I(x, y, z) (y ^ (x | ~z))

// x循环左移n位的操作
#define ROTATE_LEFT(x, n) ((x << n) | (x >> (32 - n)))

// FF,GG,HH,II是四轮循环变换分别用到的变换函数
#define FF(a, b, c, d, x, s, ac)  \
    {                             \
        a += F(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s);    \
        a += b;                   \
    }
#define GG(a, b, c, d, x, s, ac)  \
    {                             \
        a += G(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s);    \
        a += b;                   \
    }
#define HH(a, b, c, d, x, s, ac)  \
    {                             \
        a += H(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s);    \
        a += b;                   \
    }
#define II(a, b, c, d, x, s, ac)  \
    {                             \
        a += I(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s);    \
        a += b;                   \
    }

// MD5算法初始化操作
void MD5Init(MD5_CTX *context);
// 使用MD5算法对input的数据进行处理
void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen);
// 获取MD5码（由digest返回），顺便清除context数据
void MD5Final(MD5_CTX *context, unsigned char digest[16]);
// MD5变换函数
void MD5Transform(unsigned int state[4], unsigned char block[64]);
// 将无符号整数转为字节类型数组
void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len);
// 将字节类型数组转为无符号整数
void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len);

#endif